#include "OGLWindowControl.h"

OGLWindowControl::OGLWindowControl()
{
	windowName = DEFAULT_WINDOW_NAME;
	windowHeight = DEFAULT_WINDOW_HEIGHT;
	windowWidth = DEFAULT_WINDOW_WIDTH;
	enableFrameCounter = FRAME_COUNTER_ENABLED;
	oglVerMajor = DEFAULT_OPENGL_VERSION_MAJOR;
	oglVerMinor = DEFAULT_OPENGL_VERSION_MINOR;
	fsaaSamples = DEFAULT_FSAA_SAMPLES;
	glDepthFunction = DEFAULT_GL_DEPTH_FUNC;
	glCullFaceDirection = DEFAULT_CULL_FACE_DIRECTION;

	glfwEnableFlags.clear();
	glEnableFlags.clear();
}

OGLWindowControl::~OGLWindowControl(){}

OGLResult OGLWindowControl::StartControl()
{
	// Initialize GLFW - Window Manager
	if(!glfwInit())
	{
		fprintf(stderr, "[FATAL] Failed to Initialize GLFW...\n");
		return OGL_FATAL;
	}

	int retval = initWindow();
	if(retval != OGL_SUCCESS)
	{
		glfwTerminate();
		return retval;
	}

	// Initialize GLEW
	if(oglVerMajor <= 3)
	{
		glewExperimental = GL_TRUE;	// Otherwise the program segfaults at glGenVertexArrays()
	}

	GLenum glewInitResult = glewInit();
	if(glewInitResult != GLEW_OK)
	{
		fprintf(stderr, "[FATAL] Failed to Initialize GLEW...\n");
		glfwTerminate();
		return OGL_FATAL;
	}

	// Clean the drawing surface...
	glViewport(0, 0, windowWidth, windowHeight);
	glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
	
	// Set up OpenGL Optimizations
	std::vector<GLenum>::iterator it;
	for(it = glEnableFlags.begin(); it != glEnableFlags.end(); it++)
	{
		glEnable(*it);
		if(*it == GL_DEPTH_TEST)
			// Accept fragment based on relative distance to the camera and the former fragment
			glDepthFunc(glDepthFunction);
		else if(*it == GL_CULL_FACE)
			// Set the triangle culling direction
			glCullFace(glCullFaceDirection);
	}

	return OGL_SUCCESS;
}

OGLResult OGLWindowControl::StopControl()
{
	glfwTerminate();
	return OGL_SUCCESS;
}


OGLResult OGLWindowControl::initWindow()
{
	glfwOpenWindowHint(GLFW_FSAA_SAMPLES, fsaaSamples);	// Sets 4x Anit-Aliazing Samples
	glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, oglVerMajor);
	glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, oglVerMinor);
	glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);	// We dont' want old OpenGL
	glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);	// Allows forward compatibility
	glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, debugContext);	// Creates an OpenGL Debug Context

	// Create the Window
	if(!glfwOpenWindow(windowWidth, windowHeight, 0, 0, 0, 0, 32, 0, GLFW_WINDOW))
	{
		fprintf(stderr, "[FATAL] Could not create OpenGL Window...\n");
		return OGL_FATAL;
	}

	// Enable GLFW features
	std::vector<int>::iterator it;
	for(it = glfwEnableFlags.begin(); it != glfwEnableFlags.end(); it++)
		glfwEnable(*it);

	// Set window Title
	glfwSetWindowTitle(windowName.c_str());

	return OGL_SUCCESS;
}

//void GLFWCALL OGLWindowControl::windowResizeCallback(int width, int height)
//{
//	windowHeight = height;
//	windowWidth = width;
//}
